package cn.aylog.servicebase.utils;

import cn.aylog.servicebase.annotations.QueryBetween;
import cn.aylog.servicebase.annotations.QueryEquals;
import cn.aylog.servicebase.annotations.QueryIn;
import cn.aylog.servicebase.annotations.QueryLike;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class MpUtils {

    private MpUtils() {}

    /**
     * 根据name拼接方法名称
     * @param name
     * @return
     */
    private String getMethodName(String name) {
        if (null == name) {
            throw new RuntimeException("getMethodName参数 name 不能为 null");
        }
        String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
        return methodName;
    }

    /**
     * 根据方法获取值
     * @param method
     * @param data
     * @return
     */
    private Object getValueByMethod(Method method, Object data) {
        try {
            return method.invoke(data);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 强制获取值
     * @param field
     * @param data
     * @return
     */
    private Object getValueBtAccess(Field field, Object data) {
        try {
            field.setAccessible(true);
            Object value = field.get(data);
            return value;
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取field中的值
     * @param field
     * @param data
     * @return
     */
    private Object getValue(Field field, Object data) {
        Class<?> aClass = data.getClass();
        try {
            String name = field.getName();
            String methodName = getMethodName(name);
            Method method = aClass.getMethod(methodName);
            return getValueByMethod(method, data);
        } catch (NoSuchMethodException e) {
            return getValueBtAccess(field, data);
        }
    }

    /**
     * 判断是否有值
     * @param data
     * @return
     */
    public static Boolean isEmpty(Object data) {
        if(null == data) return true;
        String typeName = data.getClass().getTypeName();
        if("java.lang.String".equals(typeName)) {
            return StringUtils.isEmpty(data);
        }
        return false;
    }

    /**
     * between数据收集
     * @param field
     * @param value
     * @param between
     */
    private void collectBetweenValue(Field field, Object value, Map<String, Object[]> between) {
        Object[] values = new Object[2];
        QueryBetween anno = field.getDeclaredAnnotation(QueryBetween.class);
        String key = anno.group();
        if(StringUtils.isEmpty(key)) {
            key = anno.value();
        }
        if(between.containsKey(key)) {
            values = between.get(key);
        }

        if(anno.start()) {
            values[0] = value;
        } else {
            values[1] = value;
        }

        between.put(key, values);
    }

    /**
     * 创建查询包装类
     * @param data
     * @return
     */
    public static QueryWrapper createQueryMapper(Object data) {
        QueryWrapper wrapper = new QueryWrapper();
        MpUtils utils = new MpUtils();
        Class<?> aClass = data.getClass();
        Field[] fields = aClass.getDeclaredFields();
        // between 参数收集
        Map<String, Object[]> between = new HashMap<>();
        for (Field field : fields) {
            String name = field.getName();
            Object value = utils.getValue(field, data);
            if(field.isAnnotationPresent(QueryIn.class)) {
                if(!MpUtils.isEmpty(value)) {
                    wrapper.in(name, value);
                }
            }

            if(field.isAnnotationPresent(QueryLike.class)) {
                if(!MpUtils.isEmpty(value)) {
                    wrapper.like(name, value);
                }
            }

            if(field.isAnnotationPresent(QueryEquals.class)) {
                if(!MpUtils.isEmpty(value)) {
                    wrapper.eq(name, value);
                }
            }

            if(field.isAnnotationPresent(QueryBetween.class)) {
                utils.collectBetweenValue(field, value, between);
            }
        }

        // 处理between
        for(String key : between.keySet()) {
            Object[] values = between.get(key);
            if(!MpUtils.isEmpty(values[0]) && !MpUtils.isEmpty(values[1])) {
                wrapper.between(key, values[0], values[1]);
            }
        }

        return wrapper;
    }
}
